package com.tmc.service.baseinfo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.tmc.bean.common.CommonResult;
import com.tmc.bean.common.ContextInfo;
import com.tmc.bean.common.Pagination;
import com.tmc.constant.CacheConstant;
import com.tmc.dao.impl.AirportDaoImpl;
import com.tmc.dao.impl.CityDaoImpl;
import com.tmc.dao.impl.CountryDaoImpl;
import com.tmc.entity.baseinfo.Airport;
import com.tmc.entity.baseinfo.City;
import com.tmc.entity.baseinfo.Country;
import com.tmc.service.cache.CacheServiceImpl;
import com.tmc.util.ObjectUtil;

@Service
@Transactional
public class CityServiceImpl {

	@Autowired
	private CityDaoImpl dao;
	
	@Autowired
	private CountryDaoImpl countryDao;
	
	@Autowired
	private AirportDaoImpl airportDao;
	
	@Autowired
	private CacheServiceImpl cache;
	
	private static String all_key = "KEY_CITY_ALL";
	
	private static String map_key = "KEY_CITY_ALL_MAP";

	private Log logger = LogFactory.getLog(this.getClass());

	public Pagination<City> findByCon(ContextInfo context, City cond, int pageIndex, int pageSize) {
		Pagination<City> result = dao.findByCon(context, cond, pageIndex, pageSize);
		this.setExtInfo(result);
		return result;
	}
	
	public City getByCode(ContextInfo context, String code){
		if (ObjectUtil.noText(code)){
			return null;
		}
		List<City> citys = this.findAllFromCache(context);
		for (City city : citys){
			if (city.getCityCode().equals(code)){
				return city;
			}
		}
		return null;
	}
	
	public String getNameByCode(ContextInfo context, String code){
		City bean = this.getByCode(context, code);
		if (bean == null){
			return "";
		}
		return bean.getCityName();
	}
	
	public List<City> getByCountryCode(ContextInfo context, String code){
		if (ObjectUtil.noText(code)){
			return null;
		}
		List<City> result = new ArrayList<City>();
		List<City> citys = this.findAllFromCache(context);
		for (City city : citys){
			if (code.equals(city.getCountryCode())){
				result.add(city);
			}
		}
		return result;
	}
	
	public List<City> getByTC(ContextInfo context, String code){
		if (ObjectUtil.noText(code)){
			return null;
		}
		List<City> result = new ArrayList<City>();
		List<City> citys = this.findAllFromCache(context);
		for (City city : citys){
			if (code.equals(city.getIataArea())){
				result.add(city);
			}
		}
		return result;
	}
	
	public String getCountryCodeByCode(ContextInfo context, String code){
		City bean = this.getByCode(context, code);
		if (bean == null){
			return "";
		}
		return bean.getCountryCode();
	} 

	@SuppressWarnings("unchecked")
	public List<City> findAllFromCache(ContextInfo context) {
		if (cache.get(CacheConstant.CACHE_NAME_600, all_key) != null) {
			return (List<City>) cache.get(CacheConstant.CACHE_NAME_600, all_key);
		}
		List<City> list = dao.findAll(context);
		cache.put(CacheConstant.CACHE_NAME_600, all_key, list);
		return list;
	}

	@SuppressWarnings("unchecked")
	public Map<String, City> findMapFromCache(ContextInfo context) {
		if (cache.get(CacheConstant.CACHE_NAME_600, map_key) != null) {
			return (Map<String, City>) cache.get(CacheConstant.CACHE_NAME_600, map_key);
		}
		Map<String, City> map = this.toMap(this.findAllFromCache(context));
		cache.put(CacheConstant.CACHE_NAME_600, map_key, map);
		return map;
	}
	
	private Map<String, City> toMap(List<City> citys) {
		Map<String, City> map = new HashMap<String, City>();
		for (City city : citys) {
			map.put(city.getCityCode(), city);
		}
		return map;
	}

	@CacheEvict(value = CacheConstant.CACHE_NAME_600, key = "'KEY_CITY_ALL'")
	public CommonResult delete(ContextInfo context, Long cityId) {
		City city = dao.getById(cityId);
		if (city != null) {
			ObjectUtil.updateBaseInfo(city, context);
			city.setEnabledFlag("N");
			dao.update(city);
		}
		return CommonResult.makeSuccess("删除成功！");
	}

	public City getById(ContextInfo context, Long cityId) {
		return dao.getById(cityId);
	}

	@CacheEvict(value = CacheConstant.CACHE_NAME_600, key = "'KEY_CITY_ALL'")
	public CommonResult save(ContextInfo context, City city) {
		CommonResult check = this.check(city);
		if (!check.isSuccess()) {
			return check;
		}
		// 保存
		if (city.getCityId() == null) {
			ObjectUtil.setBaseInfo(city, context);
			dao.insert(city);
		} else {
			// 编辑
			try {
				City dbCity = dao.getById(city.getCityId());
				if (dbCity != null) {
					ObjectUtil.copyProperties(city, dbCity,
							new String[] { "createdBy", "creationDate", "cityId", "enabledFlag" });
				}
				ObjectUtil.updateBaseInfo(dbCity, context);
				// 根据国家二字码更新相关冗余字段
				if (ObjectUtil.hasText(dbCity.getCountryCode())){
					Country country = countryDao.getByCode(context, dbCity.getCountryCode());
					if (country == null) {
						logger.error("无此国家！" + dbCity.getCountryCode());
						return CommonResult.makeFail("无此国家！" + dbCity.getCountryCode());
					}
					dbCity.setCountryName(country.getCountryName());
					dbCity.setCountryNameEn(country.getCountryNameEn());
					dbCity.setContinentCode(country.getContinentCode());
					dbCity.setContinentName(country.getContinentName());
					dbCity.setContinentNameEn(country.getContinentNameEn());
				}
				dao.update(dbCity);
				// 更改关联机场
				List<Airport> airports = airportDao.findByCityCode(context, dbCity.getCityCode());
				if (airports != null && !airports.isEmpty()){
					for (Airport airport : airports){
						airport.setCityName(dbCity.getCityName());
						airport.setCityNameEn(dbCity.getCityNameEn());
						airport.setCountryCode(dbCity.getCountryCode());
						airport.setCountryName(dbCity.getCountryName());
						airport.setCountryNameEn(dbCity.getCountryNameEn());
						ObjectUtil.updateBaseInfo(airport, context);
					}
					airportDao.update(airports);
				}
			} catch (Exception e) {
				logger.error("拷贝对象错误！", e);
				return CommonResult.makeFail("拷贝对象错误！");
			}
		}
		return CommonResult.makeSuccess();
	}

	private CommonResult check(City city) {
		if (!ObjectUtil.hasText(city.getCityCode())) {
			return CommonResult.makeFail("城市三字码不能为空！");
		}
		if (!ObjectUtil.hasText(city.getCityName())) {
			return CommonResult.makeFail("城市名字不能为空！");
		}
		/*
		 * if (!ObjectUtil.hasText(airport.getCityCode())){ return
		 * CommonResult.makeFail("所属城市不能为空！"); }
		 */
		return CommonResult.makeSuccess();
	}

	private void setExtInfo(Pagination<City> result) {
		// TODO Auto-generated method stub

	}

	public void updateFromAirport(ContextInfo context) {
        List<Airport> airports = airportDao.findAll();
        for (Airport airport : airports){
        	if (ObjectUtil.hasText(airport.getCityCode())){
        		City dbCity = dao.getByCode(context, airport.getCityCode());
        		if (dbCity == null){
        			System.out.println("添加城市" + airport.getCityCode());
        			City city = new City();
        			city.setCityCode(airport.getCityCode());
        			city.setCityName(airport.getCityName());
        			city.setCityNameEn(airport.getCityNameEn());
        			city.setCountryCode(airport.getCountryCode());
        			city.setCountryName(airport.getCountryName());
        			city.setCountryNameEn(airport.getCountryNameEn());
        			city.setContinentCode(airport.getContinentCode());
        			city.setContinentName(airport.getContinentName());
        			city.setContinentNameEn(airport.getContinentNameEn());
        			city.setTimezone(airport.getTimezone());
        			ObjectUtil.setBaseInfo(city, context);
        			dao.insert(city);
        		}
        	}
        }
		System.out.println("处理完毕");
	}
	
	public void updateSelf(ContextInfo context) {
		Map<String, Country> map = new HashMap<String, Country>();
		List<City> citys = dao.findAll(context);
		for (City city : citys){
			String countryCode = city.getCountryCode();
			String countryName = city.getCountryName();
			String countryNameEn = city.getCountryNameEn();
			if (ObjectUtil.hasText(countryName)){
				if (map.containsKey(countryName)){
					Country mapBean = map.get(countryName);
					if (ObjectUtil.noText(mapBean.getCountryCode()) && ObjectUtil.hasText(countryCode)){
						mapBean.setCountryCode(countryCode);
					}
					if (ObjectUtil.noText(mapBean.getCountryNameEn()) && ObjectUtil.hasText(countryNameEn)){
						mapBean.setCountryNameEn(countryNameEn);
					}
				} else {
					Country country = new Country();
					country.setCountryCode(countryCode);
					country.setCountryName(countryName);
					country.setCountryNameEn(countryNameEn);
					map.put(countryName, country);
				}
			}
		}
		for (City city : citys){
			if (ObjectUtil.hasText(city.getCountryName())){
				Country mapBean = map.get(city.getCountryName());
				if (ObjectUtil.noText(city.getCountryCode()) && ObjectUtil.hasText(mapBean.getCountryCode())){
					city.setCountryCode(mapBean.getCountryCode());
				}
				if (ObjectUtil.noText(city.getCountryNameEn()) && ObjectUtil.hasText(mapBean.getCountryNameEn())){
					city.setCountryNameEn(mapBean.getCountryNameEn());
				}
			}
			dao.update(city);
		}
		System.out.println("处理完毕");
	}

	public void updateFromCountry(ContextInfo context) {
		List<Country> countrys = countryDao.findAll();
		List<City> citys = dao.findAll(context);
		for (City city : citys){
			String countryCode = city.getCountryCode();
			String string = city.getCityNameEn();
			if(ObjectUtil.hasText(string)){
				city.setCityNameEn(string.toUpperCase());
			}
			for (Country country : countrys){
				if (ObjectUtil.hasText(countryCode) && countryCode.equals(country.getCountryCode())){
				    city.setCountryName(country.getCountryName());
				    city.setCountryNameEn(country.getCountryNameEn());
				    city.setContinentName(country.getContinentName());
				    city.setContinentNameEn(country.getContinentNameEn());
				    city.setIataArea(country.getIataArea());
					break;
				}
			}
		}
		dao.update(citys);
		System.out.println("处理完毕");
	}
	
	/**
	 * 修改城市列表中的国家英文名字段
	 * @author zhang
	 * @return
	 *			CommonResult
	 */
	public CommonResult updateAllFromCache(){
		try {
			List<City> citys = this.findAllFromCache(null);
			for (City city : citys) {
				if(city.getCountryCode() != null){
					if(city.getCountryCode().equals("US")){
						city.setCountryNameEn("America");
					}
					if(city.getCountryCode().equals("CN")){
						city.setCountryNameEn("China");
					}
				}
			}
			System.out.println("更新成功！");
			return CommonResult.makeSuccess("更新成功！");
		} catch (Exception e) {
			logger.error("更新城市出错！", e);
		}
		return CommonResult.makeFail("更新城市出错！");
	}
	
	/**
	 * 
	 * @author zhang
	 * @param citys
	 * @return
	 */
	public CommonResult updateAllFromYITU8City(List<com.tmc.vendor.intcar.yitu8.bean.City> citys){
		Map<String, City> map = this.findMapFromCache(null);
		int i = 0;
		try {
			for (com.tmc.vendor.intcar.yitu8.bean.City yitu8City : citys) {
				City city = map.get(yitu8City.getCityCode());
				if(city != null && city.getCityName().equals(yitu8City.getName_cn()) && city.getCityCode().equals(yitu8City.getCityCode())){
					city.setYitu8CityId(yitu8City.getId());
					i++;
				}
			}
			System.out.println(i);
			return CommonResult.makeSuccess("保存成功！");
		} catch (Exception e) {
			logger.error("更新出错！", e);
		}
		return CommonResult.makeFail("更新出错");
	}

	
	public List<City> searchCity(String query){
		query = query.toUpperCase();
		List<City> citys = new ArrayList<City>();
		Map<String, City> map = this.findMapFromCache(null);
		if(ObjectUtil.noText(query)){
			citys.add(map.get("SHA"));
			citys.add(map.get("BJS"));
			citys.add(map.get("SZX"));
			citys.add(map.get("CAN"));
			citys.add(map.get("TAO"));
			citys.add(map.get("CTU"));
			citys.add(map.get("HGH"));
			citys.add(map.get("TSN"));
			citys.add(map.get("XMN"));
			return citys;
		}
		for (City city : map.values()) {
			if(city.getCityCode().indexOf(query) > -1 || city.getCityName().indexOf(query) > -1 || 
					(city.getCityName()+"("+city.getCityCode()+")").indexOf(query) > -1){
				citys.add(city);
				if(citys.size() == 8){
					return citys;
				}
			}
		}
		
		return citys;
	}
}
